package com.kayak.fapp.transbase;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.kayak.dbutil.dao.ComnDao;
import com.kayak.dbutil.sql.SqlException;
import com.kayak.dubbo.bean.ConsumerBean;
import com.kayak.dubbo.global.RpcGlobal;
import com.kayak.exception.ErrorException;
import com.kayak.kkutils.CalendarUtil;
import com.kayak.kkutils.JsonUtil;
import com.kayak.kkutils.strutil.StringUtil;
import com.kayak.kkweb.sys.Global;
import com.kayak.kkweb.sys.SysBeans;

/**
 * 交易父类
 * 20160323
 * 执行步骤说明：
 *	--->doService() 供Action调用入口
 *  --->doMain()    流程处理主函数
 *  
 *  --->securityCheck 加密校验
 *  --->initParamSuper[initParam()]  初始化公共参数，并调用子类中添加参数initParam
 *  --->dataCheckSuper[dataCheck()]  数据校验：非空及格式
 *  --->busiCheckSuper[busiCheck()]  业务数据校验
 *  --->doBusi						 业务处理
 *  --->securityOut                  组包加密
 * */
public abstract class TransBase {

	private static final Logger log = LoggerFactory.getLogger(TransBase.class);
	private Logger logUtil = LoggerFactory.getLogger(this.getClass());
	@Autowired
	public ComnDao comnDao;
	//@Autowired
	//public JedisEx jedisEx;
	/**
	 * 入口方法 根据transCode获取交易实例并执行
	 * add by guancj 20160304 
	 * Action调用的方法入口
	 * 
	 * @param transCode
	 *            交易码
	 * @param params
	 *            参数
	 * @param response
	 *            返回
	 */
	public static void doService(String transCode, Map<String, Object> params, HttpServletResponse response) {
		//String transId, String custId, String transCode, String timeStamp
		String timeStamp = new SimpleDateFormat("YYYYMMDDhh24mmssSSS").format(new Date());
		ConsumerBean consumerBean = new ConsumerBean("", "", transCode, timeStamp, "");
		if (params == null || params.size() == 0 || StringUtil.isEmpty(transCode)) {
			consumerBean.addLocalParam(RpcGlobal.RET_MSG, "服务已启动！");
			consumerBean.addLocalParam(RpcGlobal.RET_CODE, "ok");
			returnClient((ServletResponse) response, consumerBean);
			return;
		}

		consumerBean.setRequest((Map<String, Object>) params);
		consumerBean.getLocalMap().putAll(params);

		try {
			if (StringUtils.isBlank(transCode)) {
				throw new ErrorException("E999", "交易码不存在");
			}
			consumerBean.addLocalParam("trans_code", transCode);
			
			// 根据交易码生成实例
			TransBase comnService = (TransBase) SysBeans.getBean("t" + transCode);
			if (comnService == null) {
				throw new ErrorException("系统异常");
			}

			comnService.doMain(consumerBean);
			if(null==consumerBean.getLocalParam(RpcGlobal.RET_CODE)
					||consumerBean.getLocalParam(RpcGlobal.RET_CODE).equals("")){
				consumerBean.addLocalParam(RpcGlobal.RET_CODE, "0000");
				consumerBean.addLocalParam(RpcGlobal.RET_MSG, "交易成功");
			}
		} catch (ErrorException e) {
			log.error(e.getMessage());
//			e.printStackTrace();
			if (e.getErroCode() == null) {
				// 通用返回错误
				consumerBean.addLocalParam(RpcGlobal.RET_CODE, "E999");
				consumerBean.addLocalParam(RpcGlobal.RET_MSG, "系统错误！");
			} else {
				consumerBean.addLocalParam(RpcGlobal.RET_CODE, e.getErroCode());
				consumerBean.addLocalParam(RpcGlobal.RET_MSG, e.getMessage());
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage());
			consumerBean.addLocalParam(RpcGlobal.RET_CODE, "E999");
			consumerBean.addLocalParam(RpcGlobal.RET_MSG, "系统错误！");
		} finally {
			returnClient((ServletResponse) response, consumerBean);
		}
	}
	
	/**
	 * 执行请求
	 * 
	 * @param consumerBean
	 * @throws Exception
	 */
	public final void doMain(ConsumerBean consumerBean) throws Exception {
		
		
		this.securityCheck(consumerBean);
		
		this.initParamSuper(consumerBean);
		
		this.dataCheckSuper(consumerBean);
		
		this.busiCheckSuper(consumerBean);
		
		this.doBusi(consumerBean);	
		
		this.securityOut(consumerBean);

	}
	
	public void securityCheck(ConsumerBean consumerBean)throws ErrorException{
		
	}
	
	/**
	 * 公共初始化参数
	 * 
	 * @param consumerBean
	 * @throws ErrorException
	 */
	private void initParamSuper(ConsumerBean consumerBean) throws ErrorException {
		
		consumerBean.addLocalParam("trans_date", CalendarUtil.getNowTime("yyyyMMdd"));
		consumerBean.addLocalParam("trans_time", CalendarUtil.getNowTime("HHmmss"));
		
		initParam(consumerBean);
	}

	public abstract void initParam(ConsumerBean consumerBean) throws ErrorException;

	/**
	 * 公共验证参数不为空
	 * 
	 * @param consumerBean
	 * @throws ErrorException
	 */
	private void dataCheckSuper(ConsumerBean consumerBean) throws ErrorException {
		
		dataCheck(consumerBean);
	}

	/**
	 * 验证参数不为空
	 * @param consumerBean
	 * @throws ErrorException
	 */
	public abstract void dataCheck(ConsumerBean consumerBean) throws ErrorException;

	/**
	 * 公共业务逻辑校验
	 * 
	 * @param consumerBean
	 * @throws ErrorException
	 */
	private void busiCheckSuper(ConsumerBean consumerBean) throws ErrorException {
		
		busiCheck(consumerBean);
	}

	/**
	 * 业务逻辑校验
	 * 
	 * @param consumerBean
	 * @throws ErrorException
	 */
	public abstract void busiCheck(ConsumerBean consumerBean) throws ErrorException;

	public abstract void doBusi(ConsumerBean consumerBean) throws ErrorException, SqlException, Exception;

	/**
	 * 
	 * @param httpResponse
	 * @param consumerBean
	 */
	private static void returnClient(ServletResponse httpResponse, ConsumerBean consumerBean) {
		
		consumerBean.addResponse(RpcGlobal.RET_CODE, consumerBean.getLocalParam(RpcGlobal.RET_CODE));
		consumerBean.addResponse(RpcGlobal.RET_MSG, consumerBean.getLocalParam(RpcGlobal.RET_MSG));
		String retData = JsonUtil.objectToJson(consumerBean.getResponse());
		log.info("retrunClient:[{}]", retData);
		
		OutputStream out = null;
		try {
			out = httpResponse.getOutputStream();
			out.write(retData.getBytes(Global.charset()));
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		} finally {
			try {
				out.close();
			} catch (IOException e1) {
			}
		}
	}
	
	private void securityOut(ConsumerBean consumerBean)throws ErrorException {
		
	}
	
	protected void logdebug(String msg){
		logUtil.debug(msg);
	}
	
	protected void logtrace(String msg){
		logUtil.trace(msg);
	}
	
	protected void loginfo(String msg){
		logUtil.info(msg);
	}
	
	protected void logwarn(String msg){
		logUtil.warn(msg);
	}
	
	protected void logerr(String msg){
		logUtil.error(msg);
	}
	
}
